/*
    Heart of Gold engine management system
    Copyright (C) 2004 Heart of Gold development team

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * A component to support the Megasquirt fuel injection controller
 * by Bruce Bowling and Al Grippo
 *
 * @author Ryan Higgins
 * @date May 2004
 */

package com.heartOfGold.controller;

import java.util.Iterator;

import com.heartOfGold.model.Message;
import com.heartOfGold.model.megasquirtECU.MegasquirtMessenger;
import com.heartOfGold.view.FuelMaster;

public class Fuel extends Component {
    private int[] constants;
    private char lastCommand;
    private int[] realTime;
    private MegasquirtMessenger theMessenger;
    private int[] changes;
    private int[] offsets;
    private int changeCount;

    public Fuel() throws java.io.IOException {
        id = "fuel";
        panelLabel = "Megasquirt Fuel Controller";
        panel = new FuelMaster(this);
        constants = new int[125];
        realTime = new int[22];
        changes = new int[125];
        offsets = new int[125];
        changeCount = 0;
        lastCommand = 0;
        theMessenger = MegasquirtMessenger.getMessenger();
    }

    public final void parseMessage(final MegasquirtMessenger sender,
            final Message m) {
        Iterator<Object> stuff = m.getArgs();
        // The array of bytes expected as first arg of the message
        byte[] bytes = null;
        // The number of bytes in the byte array expected as
        // second arg of message
        int numBytes = 0;
        // The array where the bytes cast as ints will be stored
        int[] receiver = null;
        int temp = 0;
        // Unpack the message
        if (stuff.hasNext()) {
            bytes = (byte[]) stuff.next();
        }
        if (stuff.hasNext()) {
            numBytes = ((Integer) stuff.next()).intValue();
        }
        // Check the last command and choose the receiver of the bytes
        if (lastCommand == 'A') {
            receiver = realTime;
        } else if (lastCommand == 'V') {
            receiver = constants;
        } else {
            return;
        }
        // Transfer the contents of the byte array to receiver and cast as ints
        if (bytes != null) {
            for (int i = 0; i < numBytes; i++) {
                temp = (int) bytes[i];
                // treat bytes as unsigned as needed
                if (temp < 0) {
                    temp += 256;
                }
                receiver[i] = temp;
            }
            System.out.println("ModelHogFuel received " + numBytes
                    + " bytes!");
        }
        ((FuelMaster) panel).update(lastCommand, receiver);
        return;
    }

    public final void getConstants() throws java.io.IOException {
        int[] args = {(int) 'V'};
        sendMessage(args);
        return;
    }

    public final void burn() throws java.io.IOException {
        int[] args = {(int) 'B'};
        sendMessage(args);
        return;
    }

    public final void getRealTime() throws java.io.IOException {
        int[] args = {(int) 'A'};
        sendMessage(args);
        return;
    }

    public final void addChange(final int offset, final int value) {
        for (int i = 0; i < changeCount; i++) {
            if (offsets[i] == offset) {
                changes[i] = value;
                return;
            }
        }
        offsets[changeCount] = offset;
        changes[changeCount] = value;
        changeCount++;
        return;
    }

    public final void writeChanges() throws java.io.IOException {
        if (changeCount == 0) {
            return;
        }
        int[] args = new int[changeCount * 3];
        int argsIndex = 0;
        for (int i = 0; i < changeCount; i++) {
            args[argsIndex++] = (int) 'W';
            args[argsIndex++] = offsets[i];
            args[argsIndex++] = changes[i];
        }
        sendMessage(args);
        changeCount = 0;
        return;
    }

    private void sendMessage(final int[] intArgs) throws java.io.IOException {
        Message getC = new Message("fuel");
        int mLength = intArgs.length;
        byte[] args = new byte[mLength];
        int temp = 0;
        // convert integers to signed bytes and add to arg array
        for (int i = 0; i < mLength; ++i) {
            temp = intArgs[i];
            if (temp > 127) {
                temp -= 256;
            }
            args[i] = (byte) temp;
        }
        getC.addArg(args);
        getC.addArg(new Integer(mLength));
        theMessenger.sendMessage(getC);
        lastCommand = (char) intArgs[0];
        return;
    }
}
